import serial
import time
import re
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.animation import FuncAnimation
import threading
import queue

# 设置串口参数
ser = serial.Serial('COM5', 115200, timeout=100)  # 根据实际串口号修改
# 存储采样数据
adc_values = []

# 正则表达式用于提取采样数据
pattern = re.compile(r'/\*(\d+)\*/')

# 创建一个锁对象
data_lock = threading.Lock()

# 启动读取串口数据的线程
def read_serial_data():
    while True:
        try:
            data = ser.readline().decode("ascii").strip()  # 读取一行数据
            if data:
                match = pattern.search(data)
                if match:
                    adc_value = int(match.group(1))  # 提取ADC值
                    adc_value = round(adc_value * 3.3 / 4096-1.65, 4)
                    with data_lock:  # 确保线程安全
                        adc_values.append(adc_value)
                        if len(adc_values) > 1024:
                            adc_values.pop(0)
        except Exception as e:
            print(f"读取串口数据时出错: {e}")

# 绘制时间域曲线
def plot_time_domain(frame):
    global axes
    axes[0].cla()
    axes[0].set_xlabel("Sample Index")
    axes[0].set_ylabel("ADC Value")
    axes[0].set_title("ADC Values Over Time")
    axes[0].set_ylim(-1.8,1.8)
    with data_lock:  # 确保线程安全
        axes[0].plot(adc_values, label="ADC Value")

def plot_frequency_domain(frame):
        # 将采样数据转化为NumPy数组
    data = np.array(adc_values)
    
    # 执行FFT并计算频率
    fft_data = np.fft.fft(data)
    freq = np.fft.fftfreq(len(data), d=0.001)  # 假设采样间隔为1秒
    positive_freqs = freq[:len(freq)//2]
    positive_fft = np.abs(fft_data[:len(fft_data)//2])
    axes[1].cla()
    axes[1].plot(positive_freqs, positive_fft, label="Frequency Spectrum")
    axes[1].set_xlabel("Frequency (Hz)")
    axes[1].set_ylabel("Amplitude")
    axes[1].set_title("Frequency Spectrum")

if __name__ == "__main__":
    fig, axes = plt.subplots(1, 2)
    ani = FuncAnimation(fig, plot_time_domain, interval=200,cache_frame_data=False)  # 每100ms更新一次
    ani2 = FuncAnimation(fig, plot_frequency_domain, interval=200,cache_frame_data=False)  # 每100ms更新一次

    read_thread = threading.Thread(target=read_serial_data)
    read_thread.daemon = True
    read_thread.start()
    plt.show()

